﻿using System;
using System.Runtime.InteropServices;
using WindowsAPI.PInvoke;

namespace WindowsAPI
{
    public static partial class API
    {
        /// <summary>
        /// Функция  GetModuleHandle извлекает дескриптор указанного модуля, если файл был отображен в адресном 
        /// пространстве вызывающего процесса
        /// </summary>
        /// <param name="lpModuleName">Указатель на символьную строку с нулем в конце, которая содержит имя 
        /// модуля (или .dll или .exe файл). Если расширение имени файла опускается, в конец добавляется заданное по 
        /// умолчанию библиотечное расширение .dll. Символьная строка имени файла может включать в себя конечный 
        /// символ точки (.), который указывает, что имя модуля не имеет расширения. Строка не должна определять путь. 
        /// Когда определяется путь, убедитесь, что используются обратные слэши (\), а не прямые слэши (/). 
        /// Имя сравнивается (независимо от ситуации) с именами модулей в текущий момент отображаемыми в адресном 
        /// пространстве вызывающего процесса.</param>
        /// <returns>Если функция завершается успешно, возвращаемое значение - дескриптор указанного модуля</returns>
        [DllImport(Kernel32.FileName, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr GetModuleHandle(string lpModuleName);

        //[DllImport(Kernel32.FileName, CharSet = CharSet.Auto, SetLastError = true)]
        //public static extern IntPtr GetModuleHandleEx(string lpModuleName);

        [DllImport(Kernel32.FileName, SetLastError = true)]
        public static extern short GlobalAddAtom(string lpString);
        [DllImport(Kernel32.FileName, SetLastError = true)]
        public static extern short GlobalDeleteAtom(short nAtom);

        /// <summary>
        /// Функция извлекает адрес экспортируемой функции или переменной из заданной 
        /// динамически подключаемой библиотеки
        /// </summary>
        /// <param name="hModule">Дескриптор модуля DLL, который содержит функцию или переменную</param>
        /// <param name="procName">Указатель на символьную строку с нулем в конце, которая определяет 
        /// функцию или имя переменной, или порядковое значение функции. 
        /// Если этот параметр - порядковое значение, оно должно находиться в младшем слове; 
        /// старшее слово - должно быть нуль.</param>
        /// <returns>Если функция завершается успешно, возвращаемое значение - адрес экспортируемой функции или переменной</returns>
        [DllImport(Kernel32.FileName, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
        public static extern UIntPtr GetProcAddress(IntPtr hModule, string procName);

        /// <summary>
        /// Функция отображает заданный исполняемый модуль в адресное пространство вызывающего процесса.
        /// </summary>
        /// <param name="lpFileName">Указатель на символьную строку с нулем в конце, которая именует исполняемый 
        /// модуль (или .dll или .exe файл). Указанное имя -  это имя файла модуля и оно не связано с именем самого 
        /// сохраняемого в библиотеке модуля, как это определено ключевым словом  LIBRARY в (.def) файле определения 
        /// модуля</param>
        /// <returns>Если функция завершается успешно, возвращаемое значение - дескриптор модуля</returns>
        [DllImport(Kernel32.FileName, SetLastError = true)]
        public static extern IntPtr LoadLibrary(string lpFileName);

        /// <summary>
        /// Функция  отображает указанный исполняемый модуль в адресное пространство вызывающего процесса. 
        /// Исполняемый модуль может быть .dll или  .exe файл. Указанный модуль может заставить другие модули 
        /// отображаться в адресное пространство.
        /// </summary>
        /// <param name="lpFileName">Указатель на символьную строку с нулем в конце, которая именует исполняемый 
        /// модуль (или  .dll или  .exe файл). Указанное имя -  это имя файла исполняемого модуля. Это имя не связано 
        /// с именем самого сохраняемого в библиотеке модуля, как это определено ключевым словом  LIBRARY в (.def) 
        /// файле определения модуля</param>
        /// <param name="hFile">Этот параметр резервируется для будущего использования. Он должен быть ПУСТО (NULL).</param>
        /// <param name="dwFlags">Предпринимаемое действие при загрузке модуля. Если никакие флажки не устанавливаются,
        /// характер работы этой функции идентичен функции LoadLibrary. Этот параметр может быть одним из следующих
        /// значений.</param>
        /// <returns>Если функция завершается успешно, возвращаемое значение - дескриптор отображаемого исполняемого модуля</returns>
        [DllImport(Kernel32.FileName)]
        public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile,
            LibraryFileInfo.API.LoadLibraryFlags dwFlags);

        /// <summary>
        /// Функция  уменьшает итоговое число ссылок на загруженные динамически подключаемые библиотеки (DLL). 
        /// Когда итоговое число ссылок достигает нуля, модуль отменяет отображение в адресном пространстве вызывающего 
        /// процесса, а дескриптор становится больше не допустим.
        /// </summary>
        /// <param name="hModule">Дескриптор загруженного DLL модуля</param>
        /// <returns>Если функция завершается успешно, возвращаемое значение истина</returns>
        [DllImport(Kernel32.FileName, SetLastError = true)]
        public static extern bool FreeLibrary(IntPtr hModule);

        [DllImport("shell32.dll")]
        public static extern IntPtr ShellExecute(IntPtr hWnd, string Operation, string File, string lParams,
            string Directoty, bool ShowCmd);

        public static bool ShellExecute(string File, string Directory = null, bool ShowCmd = false)
        {
            return ShellExecute(IntPtr.Zero, "OPEN", File, null, Directory, ShowCmd) != IntPtr.Zero;
        }
    }
}
